package com.cms.common.spring;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.transform.ResultTransformer;
import org.springframework.transaction.annotation.Transactional;

import com.cms.common.hibernate.BaseDao;



/** 
 * 公共Service（可继承，也可直接使用，默认均为读写事务）.
 * <ul>
 * <li>需在applicationContext.xml中将此类配置bean</li>
 * <li>必须将fuc.common.hibernate.BaseDao配置为名为baseDao的bean，以注入此类</li>
 * </ul>
 */
@Transactional
public class BaseService {
	/* ***************baseDao***************** */
	@Resource
	private BaseDao baseDao;
	
	
	
	/* ***************代码增删改***************** */
	/** 存储实体到数据库. */
	public <PK extends Serializable> PK save(Object entity) {
		return baseDao.save(entity);
	}
	
	/** 增加或更新实体. */
	public void saveOrUpdate(Object entity) {
		baseDao.saveOrUpdate(entity);
	}
	
	/** 删除指定的实体. */
	public void delete(Object entity) {
		baseDao.delete(entity);
	}
	
	/** 更新实体. */
	public void update(Object entity) {
		baseDao.update(entity);
	}



	/* ***************HQL增删改***************** */
	/** 使用HQL语句增加、更新、删除实体. */
	public int hqlUpdate(String hql) {
		return baseDao.hqlUpdate(hql);
	}
	
	/** 使用HQL语句增加、更新、删除实体（带参数）. */
	public int hqlUpdate(String hql, Object value) {
		return baseDao.hqlUpdate(hql, value);
	}
	
	/** 使用HQL语句增加、更新、删除实体（带参数）. */
	public int hqlUpdate(String hql, Object... values) {
		return baseDao.hqlUpdate(hql, values);
	}
	
	
	
	/* ***************SQL增删改***************** */
	/** 使用SQL语句增加、更新、删除实体. */
	public int sqlUpdate(String sql) {
		return baseDao.sqlUpdate(sql);
	}
	
	/** 使用SQL语句增加、更新、删除实体（带参数）. */
	public int sqlUpdate(String sql, Object value) {
		return baseDao.sqlUpdate(sql, value);
	}
	
	/** 使用SQL语句增加、更新、删除实体（带参数）. */
	public int sqlUpdate(String sql, Object... values) {
		return baseDao.sqlUpdate(sql, values);
	}



	/* ***************代码查询***************** */
	//查询条件：无（满足最基本需要）
	/** 根据主键获取实体，如果没有则抛出异常. */
	public <T> T load(Class<T> clazz, Serializable id) {
		return baseDao.load(clazz, id);
	}
	

	//查询条件：无（满足最基本需要）
	/** 根据主键获取实体，如果没有则返回null. */
	public <T> T get(Class<T> clazz, Serializable id) {
		return baseDao.get(clazz, id);
	}
	
	/** 全部查询. */
	public <T> List<T> find(Class<T> clazz) {
		return baseDao.find(clazz);
	}
	
	/** 分页，全部查询. */
	public <T> List<T> find(Class<T> clazz, int firstResult, int maxResults) {
		return baseDao.find(clazz, firstResult, maxResults);
	}
	
	/** 获取总记录数. */
	public <T> Long count(Class<T> clazz) {
		return baseDao.count(clazz);
	}
	

	//查询条件：属性=值（满足最基本需要）
	/** 根据属性查询. */
	public <T> T getByProperty(Class<T> clazz, String propertyName, Object value) {
		return baseDao.getByProperty(clazz, propertyName, value);
	}
	
	/** 根据属性查询. */
	public <T> List<T> findByProperty(Class<T> clazz, String propertyName, Object value) {
		return baseDao.findByProperty(clazz, propertyName, value);
	}
	
	/** 分页，根据属性查询. */
	public <T> List<T> findByProperty(Class<T> clazz, String propertyName, Object value, int firstResult, int maxResults) {
		return baseDao.findByProperty(clazz, propertyName, value, firstResult, maxResults);
	}
	
	/** 获取总记录数，根据属性. */
	public Long countByProperty(Class<?> clazz, String propertyName, Object value) {
		return baseDao.countByProperty(clazz, propertyName, value);
	}

	
	//查询条件：多个属性=值，属性名值对包含于实体（满足最基本需要）
	/** 根据实体构造一个查询条件（不支持主键、关联、NULL）. */
	public <T> T getByExample(T exampleEntity) {
		return baseDao.getByExample(exampleEntity);
	}
	
	/** 根据实体构造一个查询条件（不支持主键、关联、NULL）. */
	public <T> List<T> findByExample(T exampleEntity) {
		return baseDao.findByExample(exampleEntity);
	}
	
	/** 分页，根据实体构造一个查询条件（不支持主键、关联、NULL）. */
	public <T> List<T> findByExample(T exampleEntity, int firstResult, int maxResults) {
		return baseDao.findByExample(exampleEntity, firstResult, maxResults);
	}
	
	/** 获取总记录数，根据实体构造一个查询条件（不支持主键、关联、NULL）. */
	public Long countByExample(Object exampleEntity) {
		return baseDao.countByExample(exampleEntity);
	}
	

	//查询条件：where、order by、group by、统计、去重复（满足大多数需要）
	/** 
	 * 万能唯一查询.
	 * <p>根据Criterion、Order、Projection构造查询条件，根据ResultTransformer封装查询结果</p>
	 * <ul>
	 * <li>Criterion：支持<b>where</b>，创建如Restrictions.eq(?,?)、Example.create(?)</li>
	 * <li>Order：支持<b>order by</b>，创建如Order.desc(?)</li>
	 * <li>Projection：支持<b>group by</b>、<b>统计</b>、<b>去重复</b>，创建如Projections.count(?)</li>
	 * <li>ResultTransformer：支持<b>定义结果封装类型</b>，创建如Transformers.TO_LIST</li>
	 * </ul>
	 */
	public <T> T getByAny(Class<?> clazz, Object... any) {
		return baseDao.getByAny(clazz, any);
	}
	
	/** 
	 * 万能列表查询.
	 * <p>根据Criterion、Order、Projection构造查询条件，根据ResultTransformer封装查询结果</p>
	 * <ul>
	 * <li>Criterion：支持<b>where</b>，创建如Restrictions.eq(?,?)、Example.create(?)</li>
	 * <li>Order：支持<b>order by</b>，创建如Order.desc(?)</li>
	 * <li>Projection：支持<b>group by</b>、<b>统计</b>、<b>去重复</b>，创建如Projections.count(?)</li>
	 * <li>ResultTransformer：支持<b>定义结果封装类型</b>，创建如Transformers.TO_LIST</li>
	 * </ul>
	 */
	public <T> List<T> findByAny(Class<?> clazz, Object... any) {
		return baseDao.findByAny(clazz, any);
	}
	
	/** 
	 * 万能列表分页查询.
	 * <p>根据Criterion、Order、Projection构造查询条件，根据ResultTransformer封装查询结果</p>
	 * <ul>
	 * <li>Criterion：支持<b>where</b>，创建如Restrictions.eq(?,?)、Example.create(?)</li>
	 * <li>Order：支持<b>order by</b>，创建如Order.desc(?)</li>
	 * <li>Projection：支持<b>group by</b>、<b>统计</b>、<b>去重复</b>，创建如Projections.count(?)</li>
	 * <li>ResultTransformer：支持<b>定义结果封装类型</b>，创建如Transformers.TO_LIST</li>
	 * </ul>
	 */
	public <T> List<T> findByAny(Class<?> clazz, int firstResult, int maxResults, Object... any) {
		return baseDao.findByAny(clazz, firstResult, maxResults, any);
	}
	
	/** 
	 * 万能统计.
	 * <p>根据Criterion构造查询条件；支持<b>where</b>，不支持group by；创建如Restrictions.eq(?,?)、Example.create(?)</p>
	 */
	public Long countByAny(Class<?> clazz, Criterion... criterions) {
		return baseDao.countByAny(clazz, criterions);
	}

	
	//查询条件：Criteria标准查询（最底层实现，基本满足所有需要，一般情况下用不到）
	/** Criteria唯一查询. */
	public <T> T getByCriteria(DetachedCriteria criteria) {
		return baseDao.getByCriteria(criteria);
	}
	
	/** Criteria查询. */
	public <T> List<T> findByCriteria(DetachedCriteria criteria) {
		return baseDao.findByCriteria(criteria);
	}
	
	/** Criteria分页查询. */
	public <T> List<T> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) {
		return baseDao.findByCriteria(criteria, firstResult, maxResults);
	}
	
	/** Criteria统计.<ul><li>不支持group by（因为setProjection只能调一次）</li></ul> */
	public Long countByCriteria(DetachedCriteria criteria) {
		return baseDao.countByCriteria(criteria);
	}


	
	/* ***************HQL查询***************** */
	/** 使用HQL语句检索数据. */
	public <T> List<T> hqlQuery(String hql) {
		return baseDao.hqlQuery(hql);
	}
	
	/** 使用HQL语句检索数据（带参数）. */
	public <T> List<T> hqlQuery(String hql, Object value) {
		return baseDao.hqlQuery(hql, value);
	}
	
	/** 使用HQL语句检索数据（带参数）. */
	public <T> List<T> hqlQuery(String hql, Object... values) {
		return baseDao.hqlQuery(hql, values);
	}
	
	/** 使用HQL语句检索数据，返回Iterator. */
	public <T> Iterator<T> iterate(String hql) {
		return baseDao.iterate(hql);
	}
	
	/** 使用HQL语句检索数据，返回Iterator（带参数）. */
	public <T> Iterator<T> iterate(String hql, Object value) {
		return baseDao.iterate(hql, value);
	}
	
	/** 使用HQL语句检索数据，返回Iterator（带参数）. */
	public <T> Iterator<T> iterate(String hql, Object... values) {
		return baseDao.iterate(hql, values);
	}

	
	
	/* ***************SQL查询***************** */
	//结果转为Map
	/** 使用SQL语句检索数据，并将结果以字段名或别名为key封装为Map. */
	public List<Map<String, Object>> sqlQuery(String sql) {
		return baseDao.sqlQuery(sql);
	}
	
	/** 使用SQL语句检索数据，并将结果以字段名或别名为key封装为Map（带参数）. */
	public List<Map<String, Object>> sqlQuery(String sql, Object value) {
		return baseDao.sqlQuery(sql, value);
	}
	
	/** 使用SQL语句检索数据，并将结果以字段名或别名为key封装为Map（带参数）. */
	public List<Map<String, Object>> sqlQuery(String sql, Object... values) {
		return baseDao.sqlQuery(sql, values);
	}
	
	
	//结果转为指定bean，bean的属性名与数据库字段名不同时，应在sql中使用别名
	/** 使用SQL语句检索数据，并将结果根据字段名或别名转换为clazz类型的对象. */
	public <T> List<T> sqlQuery(Class<T> clazz, String sql) {
		return baseDao.sqlQuery(clazz, sql);
	}
	
	/** 使用SQL语句检索数据，并将结果根据字段名或别名转换为clazz类型的对象（带参数）. */
	public <T> List<T> sqlQuery(Class<T> clazz, String sql, Object value) {
		return baseDao.sqlQuery(clazz, sql, value);
	}
	
	/** 使用SQL语句检索数据，并将结果根据字段名或别名转换为clazz类型的对象（带参数）. */
	public <T> List<T> sqlQuery(Class<T> clazz, String sql, Object... values) {
		return baseDao.sqlQuery(clazz, sql, values);
	}
	
	
	//结果转为指定类型
	/** 使用SQL语句检索数据，并将结果根据字段名或别名封装为resultTransformer指定类型对象. */
	public <T> List<T> sqlQuery(ResultTransformer resultTransformer, String sql) {
		return baseDao.sqlQuery(resultTransformer, sql);
	}
	
	/** 使用SQL语句检索数据，并将结果根据字段名或别名封装为resultTransformer指定类型对象（带参数）. */
	public <T> List<T> sqlQuery(ResultTransformer resultTransformer, String sql, Object value) {
		return baseDao.sqlQuery(resultTransformer, sql, value);
	}
	
	/** 使用SQL语句检索数据，并将结果根据字段名或别名封装为resultTransformer指定类型对象（带参数）. */
	public <T> List<T> sqlQuery(ResultTransformer resultTransformer, String sql, Object... values) {
		return baseDao.sqlQuery(resultTransformer, sql, values);
	}
	
	
	//结果转为指定实体，使用OR映射，查询所有字段
	/** 使用SQL语句检索数据，并将结果根据OR映射转换为实体，sql必须查询实体中包含的所有字段，否则报错. */
	public <T> List<T> sqlQueryEntity(Class<T> clazz, String sql) {
		return baseDao.sqlQueryEntity(clazz, sql);
	}
	
	/** 使用SQL语句检索数据，并将结果根据OR映射转换为实体，sql必须查询实体中包含的所有字段，否则报错（带参数）. */
	public <T> List<T> sqlQueryEntity(Class<T> clazz, String sql, Object value) {
		return baseDao.sqlQueryEntity(clazz, sql, value);
	}
	
	/** 使用SQL语句检索数据，并将结果根据OR映射转换为实体，sql必须查询实体中包含的所有字段，否则报错（带参数）. */
	public <T> List<T> sqlQueryEntity(Class<T> clazz, String sql, Object... values) {
		return baseDao.sqlQueryEntity(clazz, sql, values);
	}
	


	/* ***************其它***************** */
	/** 关闭返回的Iterator. */
	public void closeIterator(Iterator<?> it) {
		baseDao.closeIterator(it);
	}
	
	/** 清理缓存，执行SQL（只用当使用触发器，或把Hibernate和JDBC混合使用，直接调用session.flush()才是有意义的）. */
	public void flush() {
		baseDao.flush();
	}
	
	/** 把指定的实体对象从缓冲区进行清除，使之成为游离对象. */
	public void clear() {
		baseDao.clear();
	}
	
	/** 把缓冲区内的全部对象清除(但不包括操作中的对象)，使所有实体成为游离对象，延迟加载器的session也将清空，因此会导致延迟加载时报异常. */
	public void evict(Object entity) {
		baseDao.evict(entity);
	}
	
}